<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Chapter&nbsp;13.&nbsp;异步续前（Asynchronous continuations）</title>
    <link rel="stylesheet" href="css/html.css" type="text/css">
    <meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
    <link rel="home" href="index.html" title="JBoss jBPM 3.1">
    <link rel="up" href="index.html" title="JBoss jBPM 3.1">
    <link rel="previous" href="scheduler.html" title="Chapter&nbsp;12.&nbsp;Scheduler">
    <link rel="next" href="businesscalendar.html" title="Chapter&nbsp;14.&nbsp;Business calendar">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
    <table width="100%" summary="Navigation header">
        <tr>
            <th colspan="3" align="center">Chapter&nbsp;13.&nbsp;异步续前（Asynchronous continuations）</th>
        </tr>
        <tr>
            <td width="20%" align="left"><a accesskey="p" href="scheduler.html">Prev</a>&nbsp;</td>
            <th width="60%" align="center">&nbsp;</th>
            <td width="20%" align="right">&nbsp;<a accesskey="n" href="businesscalendar.html">Next</a></td>
        </tr>
    </table>
    <hr>
</div>
<div class="chapter" lang="cn">
<div class="titlepage">
    <div>
        <div><h2 class="title"><a name="asynchronouscontinuations"></a>Chapter&nbsp;13.&nbsp;异步续前（Asynchronous continuations）
        </h2></div>
    </div>
    <div></div>
</div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="theconcept"></a>13.1.&nbsp;异步续前的概念</h2></div>
        </div>
        <div></div>
    </div>
    <p>jBPM is based on Graph Oriented Programming (GOP). Basically, GOP specifies a
        simple state machine that can handle concurrent paths of execution. But in the execution
        algorithm specified in GOP, all state transitions are done in a single operation in the
        thread of the client. If you're not familiar with the execution algorithm defined in
        <a href="graphorientedprogramming.html" title="Chapter&nbsp;4.&nbsp;Graph Oriented Programming">Chapter&nbsp;4,
            <i>Graph Oriented Programming</i></a>, please read that first. By default, this
        performing state transitions in the thread of the client is a good approach cause it fits
        naturally with server side transactions. The process execution moves from one wait state
        to another wait state in one transaction.
    </p>

    <p>But in some situations, a developer might want to fine-tune the transaction
        demarcation in the process definition. In jPDL, it is possible to specify that the process
        execution should continue asynchronously with the attribute <tt class="literal">async="true"</tt>.
        <tt class="literal">async="true"</tt> can be specified on all node types and all action types.
    </p></div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="anexample"></a>13.2.&nbsp;一个例子</h2></div>
        </div>
        <div></div>
    </div>
    <p>Normally, a node is always executed after a token has entered the node. So the node is
        executed in the thread of the client. We'll explore asynchronous continuations by looking
        two examples. The first example is a part of a process with 3 nodes. Node 'a' is a wait
        state, node 'b' is an automated step and node 'c' is again a wait state. This process does
        not contain any asynchronous behaviour and it is represented in the picture below.
    </p>

    <p>The first frame, shows the starting situation. The token points to node 'a', meaning
        that the path of execution is waiting for an external trigger. That trigger must be given
        by sending a signal to the token. When the signal arrives, the token will be passed from
        node 'a' over the transition to node 'b'. After the token arrived in node 'b', node 'b'
        is executed. Recall that node 'b' is an automated step that does not behave as a wait
        state (e.g. sending an email). So the second frame is a snapshot taken when node 'b' is
        being executed. Since node 'b' is an automated step in the process, the execute of node
        'b' will include the propagation of the token over the transition to node 'c'. Node 'c'
        is a wait state so the third frame shows the final situation after the signal method
        returns.
    </p>

    <div class="figure"><a name="async1.image"></a>

        <div class="mediaobject" align="center"><img src="images/async1.gif" align="middle"
                                                     alt="Example 1: Process without asynchronous continuation"></div>
        <p class="title"><b>Figure&nbsp;13.1.&nbsp;Example 1: Process without asynchronous continuation</b></p></div>
    <p>While persistence is not mandatory in jBPM, the most common scenario is that a signal
        is called within a transaction. Let's have a look at the updates of that transaction.
        First of all, the token is updated to point to node 'c'. These updates are generated by
        hibernate as a result of the <tt class="literal">GraphSession.saveProcessInstance</tt> on a
        JDBC connection. Second, in case the automated action would access and update some
        transactional resources, those transactional updates should be combined or part of
        the same transaction.
    </p>

    <p>Now, we are going to look at the second example, the second example is a variant of
        the first example and introduces an asynchronous continuation in node 'b'. Nodes 'a' and
        'c' behave the same as in the first example, namely they behave as wait states. In jPDL,
        a node is marked as asynchronous by setting the attribute <tt class="literal">async="true"</tt>.
    </p>

    <p>The result of adding <tt class="literal">async="true"</tt> to node 'b' is that the process
        execution will be split up into 2 parts. The first part will execute the process up to
        the point where node 'b' is to be executed. The second part will execute node 'b' and
        that execution will stop in wait state 'c'.
    </p>

    <p>The transaction will hence be split up into 2 separate transactions. One transaction
        for each part. While it requires an external trigger (the invocation of the
        <tt class="literal">Token.signal</tt> method) to leave node 'a' in the first transaction, jBPM
        will automatically trigger and perform the second transaction.
    </p>

    <div class="figure"><a name="asynchronous.continuations.image"></a>

        <div class="mediaobject" align="center"><img src="images/asynchronous.continuations.gif" align="middle"
                                                     alt="Example 2: A process with asynchronous continuations"></div>
        <p class="title"><b>Figure&nbsp;13.2.&nbsp;Example 2: A process with asynchronous continuations</b></p></div>
    <p>For actions, the principle is similar. Actions that are marked with the
        attribute <tt class="literal">async="true"</tt> are executed outside of the thread that
        executes the process. If persistence is configured (it is by default), the actions
        will be executed in a separate transaction.
    </p>

    <p>In jBPM, asynchronous continuations are realized by using an asynchronous messaging
        system. When the process execution arrives at a point that should be executed
        asynchronously, jBPM will suspend the execution, produces a command message and send it
        to the command executor. The command executor is a separate component that, upon receipt
        of a message, will resume the execution of the process where it got suspended.
    </p>

    <p>jBPM can be configured to use a JMS provider or its built-in asynchronous messaging
        system. The built-in messaging system is quite limited in functionality, but allowes
        this feature to be supported on environments where JMS is unavailable.
    </p></div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="thecommandexecutor"></a>13.3.&nbsp;命令执行器
            </h2></div>
        </div>
        <div></div>
    </div>
    <p>The command executor is the component that resumes process executions asynchronously.
        It waits for command messages to arrive over an asynchronous messaging system and executes
        them. The two commands used for asynchronous continuations are
        <tt class="literal">ExecuteNodeCommand</tt> and <tt class="literal">ExecuteActionCommand</tt>.
    </p>

    <p>These commands are produced by the process execution. During process execution,
        for each node that has to be executed asynchronously, an <tt class="literal">ExecuteNodeCommand</tt>
        (POJO) will be created in the <tt class="literal">MessageInstance</tt>. The message instance
        is a non-persistent extension of the ProcessInstance and it just collects all the
        messages that have to be sent.
    </p>

    <p>The messages will be sent as part of the <tt class="literal">GraphSession.saveProcessInstance</tt>.
        The implementation of that method includes a context builder that acts as an aspect on
        the saveProcessInstance method. The actual interceptors can be configured in the
        <tt class="literal">jbpm.cfg.xml</tt>. One of the interceptors, <tt class="literal">SendMessagesInterceptor</tt>,
        is
        configured by default and will read the messages from the <tt class="literal">MessageInstance</tt>
        and send them over the configurable asynchronous messaging system.
    </p>

    <p>The <tt class="literal">SendMessagesInterceptor</tt> uses the interfaces
        <tt class="literal">MessageServiceFactory</tt> and <tt class="literal">MessageService</tt> to
        send messages. This is to make the asynchronous messaging implementation
        configurable (also in <tt class="literal">jbpm.cfg.xml</tt>).
    </p></div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="jbpmsbuiltinasynchronousmessaging"></a>13.4.&nbsp;jBPM的内置异步消息</h2></div>
        </div>
        <div></div>
    </div>
    <p>When using jBPM's built-in asynchronous messaging, messages will be send by persisting
        them to the database. This message persisting can be done in the same transaction/jdbc
        connection as the jBPM process updates.
    </p>

    <p>The command messages will be stored in the <tt class="literal">JBPM_MESSAGE</tt> table.
    </p>

    <p>The POJO command executor (<tt class="literal">org.jbpm.msg.command.CommandExecutor</tt>)
        will read the messages from the database table and execute them. So the typical
        transaction of the POJO command executor looks like this: 1) read next command message
        2) execute command message 3) delete command message.
    </p>

    <p>If execution of a command message fails, the transaction will be rolled back.
        After that, a new transaction will be started that adds the error message to the
        message in the database. The command executor filters out all messages that contain
        an exception.
    </p>

    <div class="figure"><a name="pojo.command.executor.image"></a>

        <div class="mediaobject" align="center"><img src="images/pojo.command.executor.gif" align="middle"
                                                     alt="POJO command executor transactions"></div>
        <p class="title"><b>Figure&nbsp;13.3.&nbsp;POJO command executor transactions</b></p></div>
    <p>If for some reason or another, the transaction that adds the exception to the
        command message would fail, it is rolled back as well. In that case, the
        message remains in the queue without an exception so it will be retried later.
    </p>

    <p>Limitation: beware that jBPM's built-in asynchronous messaging system does
        not support multinode locking. So you cannot just deploy the POJO command
        executor multiple times and have them configured to use the same database.
    </p></div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="jbpmforasyncarchitectures"></a>13.5.&nbsp;异步架构中的JMS</h2></div>
        </div>
        <div></div>
    </div>
    <p>The asynchronous continuations feature, opens up a new world of jBPM usage
        scenarios. Where typically, jBPM is used for modelling business processes,
        it can now be used from a more technical perspective.
    </p>

    <p>Imagine that you have
        an application with quite some asynchronous processing. That typically requires
        quite a bit if difficult set up to bind all the message producing and message
        consuming pieces of software together. With jBPM it now becomes possible to
        create a picture of the overall asynchronous architecture, have all your
        code in POJO's and add transaction demarcation in the overall process file.
        jBPM will now take care of binding the senders to the receivers without the
        need for writing all the JMS or MDB code yourself.
    </p></div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="jmsforasychronousmessaging"></a>13.6.&nbsp;异步消息中的JMS</h2></div>
        </div>
        <div></div>
    </div>
    <p>TODO (not yet implemented)</p></div>
<div class="section" lang="cn">
    <div class="titlepage">
        <div>
            <div><h2 class="title" style="clear: both"><a name="futuredirections"></a>13.7.&nbsp;未来的方向</h2>
            </div>
        </div>
        <div></div>
    </div>
    <p>TODO's: add support for multiple queues. So that it becomes possible to
        specify a queue for each node or action that is marked as asynchronous. Also it would
        be great to produce message for a set of queues in a round-robin. Since all of
        this should be configurable for both the JMS and the built-in messaging systems,
        this will require some thought on how to do all this configurations. The process
        definitions should not have to depend on any of the 2 possible implementations.
    </p></div>
</div>
<div class="navfooter">
    <hr>
    <table width="100%" summary="Navigation footer">
        <tr>
            <td width="40%" align="left"><a accesskey="p" href="scheduler.html">Prev</a>&nbsp;</td>
            <td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td>
            <td width="40%" align="right">&nbsp;<a accesskey="n" href="businesscalendar.html">Next</a></td>
        </tr>
        <tr>
            <td width="40%" align="left" valign="top">Chapter&nbsp;12.&nbsp;Scheduler&nbsp;</td>
            <td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td>
            <td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;14.&nbsp;Business calendar</td>
        </tr>
    </table>
</div>
</body>
</html>
